﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.ContourBuilder.Operations;

namespace ITAP.ContourBuilder.Manipulation
{
    public class ExecuteManager
    {
        private IExecutable defaultExecutable;

        public IExecutable DefaultExecutable
        {
            get { return defaultExecutable; }
            set { defaultExecutable = value; }
        }

        private ContourManipulator manipulator;
        public ExecuteManager(ContourManipulator manipulator)
        {
            this.manipulator = manipulator;
            this.manipulator.CommandExecuted += new CommandExecutedDelegate(manipulator_CommandExecuted);

            // TODO: Здесь задаются типы action'ов, которые не могут выполняться одновременно.
            this.mutuallyExclusiveExecutableTypes = new List<Type>();
            mutuallyExclusiveExecutableTypes.Add(typeof(ActionSelectMoveChangeDelete));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandEnterPolyline));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandEnterText));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddCommentLine));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddElementDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddArcHeightDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddArcRadiusDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddArcRadiusDimension2));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddElementLeaderDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddComponentLeaderDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddHole));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddDiameterDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddRemoteRadiusDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddDirectDistanceDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandAddOffsetFromMainBorderDimension));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandCreateCutout));
            mutuallyExclusiveExecutableTypes.Add(typeof(CommandOperation));
        }

        void manipulator_CommandExecuted(ICommand command)
        {
            if (this.mutuallyExclusiveExecutableTypes.Contains(command.GetType()))
                this.Execute(defaultExecutable); 
        }

        private List<Type> mutuallyExclusiveExecutableTypes;
        /// <summary>
        /// Определяет список выполнимых действий, которые подлежат завершению перед выполнением 
        /// другого действия из этого списка. Например, нельзя одновременно вводить полилинию и 
        /// выделять компоненты - эти два действия взаимоисключаемы. Тогда типы этих команд должны быть в 
        /// списке во избежание некорректной работы.
        /// </summary>
        public List<Type> MutuallyExclusiveExecutableTypes
        {
            get { return mutuallyExclusiveExecutableTypes; }
        }

        public void Execute(IExecutable executable)
        {
            if (mutuallyExclusiveExecutableTypes.Contains(executable.GetType()))
            {
                foreach (Type type in mutuallyExclusiveExecutableTypes)
                    manipulator.Terminate(type);
            }
            if (executable is IOperation)
                manipulator.Execute(executable as IOperation);
            else if (executable is ICommand)
                manipulator.Execute(executable as ICommand);            
        }
    }
}
